#setwd("C:/Users/erussek/forage_jsp/analysis")
setwd("/Users/evanrussek/forage_jsp/analysis")
rm(list = ls())
library(tidyr)
Attaching package: ‘tidyr’
The following object is masked from ‘package:Matrix’:
expand
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(zoo)
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
library(ggplot2)
library(ggpubr)
Loading required package: magrittr
Attaching package: ‘magrittr’
The following object is masked from ‘package:tidyr’:
extract
library(RcppRoll)
library(knitr)
data <- read.csv('data/run4_data.csv')
head(data)
data <- data %>% ungroup() %>% bind_cols(s_num = group_indices(., subjectID))
data <- data %>% mutate(subj = factor(s_num))
travel_keys = data %>% ungroup() %>% select(travel_key) %>% unique()
clean_subj_data <- function(subj_data, travel_keys){
travel_key_hard = travel_keys$travel_key[1]
travel_key_easy = travel_keys$travel_key[2]
subj_data <- data %>%select(round, phase, reward_obs, reward_true, lag, exit, start_reward, n_travel_steps,
travel_key, subjectID, trial_num, s_num, correct_key) %>% group_by(trial_num) %>%
mutate(press_num = 1:n(), round = as.factor(round),
rep_number = case_when(trial_num < 7 ~ 1, TRUE ~ 2)) %>%
mutate(phase = replace(phase, phase == "Harvest", "HARVEST"))
subj_data <- subj_data %>% group_by(trial_num) %>%
mutate(travel_key = replace(travel_key, travel_key == "", first(travel_key[travel_key != ""]))) %>%
mutate(travel_key_cond = case_when(travel_key == travel_key_hard ~ "HARD",
travel_key == travel_key_easy ~ "EASY")) %>%
filter(!is.na(travel_key_cond))
}
# clean all the data and bind
datalist <- list()
for (i in 1:10){
subj_data <- data %>% filter(s_num == i)
subj_data <- clean_subj_data(subj_data, travel_keys)
subj_data <- ungroup(subj_data)
datalist[[i]] <- subj_data
}
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vector
#cdata <- do.call(rbind,datalist)
cdata <- bind_rows(datalist)
# make a function to plot reward on each game...
plot_subj_reward_v_press <- function(subj_data){
s_num <- subj_data$s_num[1]
# reward plots which show the threshold...
rew_plot <- ggplot(subj_data, aes(x = press_num, y = reward_obs, group = round)) +
#geom_rect(data = t1_data, aes(xmin = press_num - 0.5, xmax = press_num + 0.5, ymin = -Inf, ymax = Inf, fill = round)) +
geom_point(aes(color = phase)) + facet_grid(n_travel_steps ~ travel_key_cond) + theme(legend.position = "none") + ylim(0,110) + ggtitle(paste("subj: ", s_num))
# plot_an <- annotate_figure(plot, top = paste('subj: ', s_num))
plot(rew_plot)
}
for (s in 1:22){
subj_data <- cdata %>% filter(s_num == s)
plot_subj_reward_v_press(subj_data)
}





















<<<<<<< HEAD

=======

>>>>>>> origin/master
get_trial_exits <- function(thdata){
# get harvest
last_phase <- last(thdata$phase)
# go through data.. if last phase was harvest, remove that round...
if (last_phase == "HARVEST"){
last_round <- last(thdata$round)
# get the last reward ops...
last_reward_ob <- last(thdata$reward_obs[!is.na(thdata$reward_obs)])
#if (last_reward_ob > 8){
thdata <- thdata %>% filter(round != last_round)
#}
}
# now select harvest data
thdata <- thdata %>% filter(phase == "HARVEST", !is.na(reward_obs)) # find out why reward_true has so many .na
## get either last true reward observed
return_tbl <- thdata %>%
group_by(round) %>%
summarise(s_num = first(s_num), last_reward = last(reward_obs),
trial_num = first(trial_num),
n_travel_steps = first(n_travel_steps),
travel_key_cond = first(travel_key_cond),
rep_number = first(rep_number)) %>% ungroup()
return(return_tbl)
}
#sdata %>% group_by(trial_num) %>%
# do(get_trial_exits(.))
exit_data <- cdata %>% group_by(s_num, trial_num) %>%
do(get_trial_exits(.)) %>% ungroup() %>% mutate(subj = as.factor(s_num))
library(ggpubr)
exit_data <- exit_data %>% mutate(round_num = as.integer(as.character(round)))
for (s in 1:22){
p <- ggplot(exit_data %>% filter(s_num == s), aes(x = round_num, y = last_reward)) + geom_point() + geom_line() +
facet_grid(n_travel_steps ~ travel_key_cond) + theme_minimal() + ylim(0,100) + ylab('last reward collected') + xlab('harvest number')
#plot(p)
#ggarrange(p)
a <- annotate_figure(p, right = "# travel steps", top = "travel step difficulty", fig.lab = paste('subj: ' , s))
plot(a)
}
geom_path: Each group consists of only one observation. Do you need to adjust the
group aesthetic?






















<<<<<<< HEAD

=======

>>>>>>> origin/master
# do some aggregating over exit thresholds...
# just get the mean for each subject for each timepoint, collapse accross rep number...
mn_exit <- exit_data %>% group_by(s_num, n_travel_steps, travel_key_cond) %>%
summarise(rep_exit_thresh = mean(last_reward), trial_num = mean(trial_num)) %>%
group_by(s_num, n_travel_steps, travel_key_cond) %>%
summarise(exit_thresh = mean(rep_exit_thresh), trial_num = mean(trial_num)) %>%
mutate(subj = as.factor(s_num)) %>% ungroup()
Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vector
# now just plot this for each subject -- draw lines to show easy - hard effect
ggplot(mn_exit, aes(x = travel_key_cond, y = exit_thresh)) + geom_dotplot(binaxis = 'y', aes(fill = subj), dotsize = 1.2) + geom_line(aes(group = subj, color = subj), size = 1.2) +
facet_grid(.~n_travel_steps) + theme_minimal() + labs(y = 'Mean Last Reward Collected', x = 'Travel Sequence', subtitle = '# Travel Presses') #theme(legend.position = "none")
<<<<<<< HEAD

=======

>>>>>>> origin/master
ggplot(mn_exit, aes(x = factor(n_travel_steps), y = exit_thresh)) +
geom_dotplot(binaxis = 'y', aes(fill = subj), dotsize = 1.2) +
geom_line(aes(group = subj, color = subj), size = 1.2) +
facet_grid(.~travel_key_cond) +
theme_minimal() +
labs(y = 'Mean Last Reward Collected', x = 'Travel Key Condition', subtitle = '# Travel Presses')
<<<<<<< HEAD

=======

>>>>>>> origin/master
#theme(legend.position = "none")
# plot the means for each of these...
gmn_exit <- mn_exit %>% group_by(n_travel_steps, travel_key_cond) %>% summarise(gm_thresh = mean(exit_thresh), gsd_thresh = sd(exit_thresh)/sqrt(n()))
ggplot(gmn_exit, aes(x = factor(n_travel_steps), y = gm_thresh, color = travel_key_cond)) +
geom_line(aes(group = travel_key_cond), size = 2) +
geom_errorbar(aes(ymin = gm_thresh - gsd_thresh, ymax = gm_thresh+gsd_thresh), width = .1, size = 2) +
geom_point(size = 4) + ylab('group mean exit threshold') + xlab('# travel steps') + labs(color = 'travel effort') + theme_minimal()
<<<<<<< HEAD

=======

>>>>>>> origin/master
library(optimx)
library(lmerTest)
exit_model <- lmer(last_reward ~ n_travel_steps + travel_key_cond + (1 + n_travel_steps + travel_key_cond |subj), data = exit_data, control = lmerControl(optimizer ="optimx",optCtrl=list(method='nlminb')))
summary(exit_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: last_reward ~ n_travel_steps + travel_key_cond + (1 + n_travel_steps +
travel_key_cond | subj)
Data: exit_data
Control: lmerControl(optimizer = "optimx", optCtrl = list(method = "nlminb"))
REML criterion at convergence: 6956.1
Scaled residuals:
Min 1Q Median 3Q Max
-4.1827 -0.5108 0.0002 0.5046 5.3563
Random effects:
Groups Name Variance Std.Dev. Corr
subj (Intercept) 290.72330 17.0506
n_travel_steps 0.06055 0.2461 -0.27
travel_key_condHARD 68.01256 8.2470 -0.25 0.26
Residual 87.82008 9.3712
Number of obs: 928, groups: subj, 22
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 54.95291 3.71001 20.77742 14.812 1.63e-12 ***
n_travel_steps -0.24696 0.06318 19.11207 -3.909 0.000935 ***
travel_key_condHARD -5.06293 1.89212 17.91918 -2.676 0.015465 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) n_trv_
n_trvl_stps -0.309
trvl_k_HARD -0.256 0.206
library(broom.mixed)
Registered S3 methods overwritten by 'broom.mixed':
method from
augment.lme broom
augment.merMod broom
glance.lme broom
glance.merMod broom
glance.stanreg broom
tidy.brmsfit broom
tidy.gamlss broom
tidy.lme broom
tidy.merMod broom
tidy.rjags broom
tidy.stanfit broom
tidy.stanreg broom
td <- tidy(exit_model, conf.int = TRUE)
tdsome <- td %>% filter(term == 'n_travel_steps' | term == 'travel_key_condHARD')
tdsome <- tdsome %>% mutate(parameter = case_when(term == 'n_travel_steps' ~ 'travel step', term == 'travel_key_condHARD' ~ 'travel effort cond'))
ggplot(tdsome, aes(estimate,parameter,color = parameter)) +
geom_point(size = 2) +
geom_errorbarh(aes(xmin = conf.low, xmax = conf.high), size = 1.2) + theme(legend.position = "none") + theme_minimal() + ylab('fixed effect') + xlab('estimate (# points)') + ggtitle('linear mixed effects model - effect on exit threshold') + theme(axis.text.y = element_text(angle = 90, hjust = .5))
<<<<<<< HEAD

=======

>>>>>>> origin/master
# reaction times...
## a bit more sensible...
lag_data <- cdata %>% select(s_num, rep_number, travel_key_cond, n_travel_steps, phase, trial_num, lag, correct_key, round, trial_num) %>% mutate(log_lag = log(lag)) %>% group_by(s_num, trial_num, round, phase) %>% slice(-1) %>% ungroup() %>% mutate(subj = as.factor(s_num))
ggplot(lag_data, aes(x=lag)) + geom_histogram(binwidth = 10) + xlim(50,300) + facet_wrap( ~ s_num)
<<<<<<< HEAD

=======

>>>>>>> origin/master
#ggplot(lag_data, aes(x=log_lag)) + geom_histogram(binwidth = .01) + facet_wrap( ~ s_num)
filt_lag <- lag_data %>% group_by(s_num) %>% filter(log_lag < (mean(log_lag) + 3*sd(log_lag)) , log_lag > (mean(log_lag) - 3*sd(log_lag))) %>% ungroup()
ggplot(filt_lag, aes(x=lag)) + geom_histogram(binwidth = 10) + facet_wrap(~s_num) + xlim(50,350)
<<<<<<< HEAD

=======

>>>>>>> origin/master
ggplot(filt_lag, aes(x=log_lag)) + geom_histogram(binwidth = .02) + facet_wrap(~s_num)
<<<<<<< HEAD

=======

>>>>>>> origin/master
NA
NA
NA
## with a run, plot the mean lag
round_filt_lag <- filt_lag %>%
group_by(s_num, n_travel_steps, travel_key_cond, round, phase) %>%
summarise(trial_num = first(trial_num), mean_lag = mean(lag), mean_log_lag = mean(log_lag)) %>% mutate(round_num = as.integer(as.character(round)))
# plot mean lag as a function of round number
lag_by_round <- round_filt_lag %>% group_by(s_num, round_num) %>% summarise(mean_lag = mean(mean_lag))
ggplot(lag_by_round, aes(x= round_num, y = mean_lag)) + geom_point() + geom_line() + facet_wrap(~s_num)
<<<<<<< HEAD

=======

>>>>>>> origin/master
trial_filt_lag <- round_filt_lag %>%
group_by(s_num, n_travel_steps, travel_key_cond, phase) %>%
summarise(trial_num = first(trial_num),
mean_lag = mean(mean_lag),
mean_log_lag = mean(mean_log_lag)) %>% ungroup() %>% mutate(s_num = as.factor(s_num))
ggplot(trial_filt_lag,
aes(x = factor(n_travel_steps), y = mean_lag, fill = s_num)) +
geom_point(aes(color = s_num), size = 2)+
geom_line(aes(group = s_num, color = s_num), size = 1.2) +
facet_grid(phase ~ travel_key_cond) + theme_minimal()
<<<<<<< HEAD

=======

>>>>>>> origin/master
ggplot(trial_filt_lag,
aes(x = travel_key_cond, y = mean_lag, fill = s_num)) +
geom_point(aes(color = s_num), size = 2)+
geom_line(aes(group = s_num, color = s_num), size = 1.2) +
facet_grid(phase ~ n_travel_steps) + theme_minimal()
<<<<<<< HEAD

=======

>>>>>>> origin/master
rr
group_lag <- trial_filt_lag %>% group_by(n_travel_steps, travel_key_cond, phase) %>% summarise(gm_lag = mean(mean_lag), gml_lag = mean(mean_log_lag)) %>% ungroup()
ggplot(group_lag, aes(x = factor(n_travel_steps), y = gm_lag, color = travel_key_cond)) + geom_line(aes(group = travel_key_cond), size = 2) + facet_wrap(~phase) + geom_point(size = 2)
<<<<<<< HEAD

=======

>>>>>>> origin/master
rr # geom_errorbar(aes(ymin = gm_thresh - gsd_thresh, ymax = gm_thresh+gsd_thresh), width = .1, size = 2) + #geom_point(size = 4) + ylab(‘group mean exit threshold’) + xlab(‘# travel steps’) + labs(color = ‘travel effort’) + theme_minimal()
rr harvest_lag <- filt_lag %>% ungroup() %>% filter(phase == ) hl_model <- lmer(log_lag ~ trial_num + n_travel_steps + travel_key_cond + (1 + trial_num + n_travel_steps + travel_key_cond |subj), data = harvest_lag, control = lmerControl(optimizer =,optCtrl=list(method=‘nlminb’)))
rr summary(hl_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: log_lag ~ trial_num + n_travel_steps + travel_key_cond + (1 + trial_num + n_travel_steps + travel_key_cond | subj)
Data: harvest_lag
Control: lmerControl(optimizer = \optimx\, optCtrl = list(method = \nlminb\))
REML criterion at convergence: -318425.9
Scaled residuals:
Min 1Q Median 3Q Max
-8.1768 -0.4915 -0.0665 0.3443 12.1230
Random effects:
Groups Name Variance Std.Dev. Corr
subj (Intercept) 3.952e-02 0.198786
trial_num 6.360e-04 0.025220 -0.62
n_travel_steps 2.484e-05 0.004984 0.13 -0.48
travel_key_condHARD 8.152e-03 0.090291 -0.01 0.16 -0.37
Residual 3.686e-02 0.191985
Number of obs: 689562, groups: subj, 22
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 5.1600968 0.0423935 20.9468771 121.719 <2e-16 ***
trial_num -0.0060976 0.0053850 21.1720321 -1.132 0.270
n_travel_steps -0.0005989 0.0010634 21.0256448 -0.563 0.579
travel_key_condHARD 0.0150356 0.0192651 21.0227579 0.780 0.444
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) trl_nm n_trv_
trial_num -0.620
n_trvl_stps 0.130 -0.476
trvl_k_HARD -0.007 0.159 -0.366
convergence code: 0
Model failed to converge with max|grad| = 0.00210383 (tol = 0.002, component 1)
<<<<<<< HEAD
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgoKCmBgYHtyfQojc2V0d2QoIkM6L1VzZXJzL2VydXNzZWsvZm9yYWdlX2pzcC9hbmFseXNpcyIpCnNldHdkKCIvVXNlcnMvZXZhbnJ1c3Nlay9mb3JhZ2VfanNwL2FuYWx5c2lzIikKcm0obGlzdCA9IGxzKCkpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoem9vKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KFJjcHBSb2xsKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCmBgYHtyfQpkYXRhIDwtIHJlYWQuY3N2KCdkYXRhL3J1bjRfZGF0YS5jc3YnKQpoZWFkKGRhdGEpCmRhdGEgPC0gZGF0YSAlPiUgdW5ncm91cCgpICU+JSBiaW5kX2NvbHMoc19udW0gPSBncm91cF9pbmRpY2VzKC4sIHN1YmplY3RJRCkpCmRhdGEgPC0gZGF0YSAlPiUgbXV0YXRlKHN1YmogPSBmYWN0b3Ioc19udW0pKQpgYGAKCmBgYHtyfQp0cmF2ZWxfa2V5cyA9IGRhdGEgJT4lIHVuZ3JvdXAoKSAlPiUgc2VsZWN0KHRyYXZlbF9rZXkpICU+JSB1bmlxdWUoKQpjbGVhbl9zdWJqX2RhdGEgPC0gZnVuY3Rpb24oc3Vial9kYXRhLCB0cmF2ZWxfa2V5cyl7CiAgdHJhdmVsX2tleV9oYXJkID0gdHJhdmVsX2tleXMkdHJhdmVsX2tleVsxXQogIHRyYXZlbF9rZXlfZWFzeSA9IHRyYXZlbF9rZXlzJHRyYXZlbF9rZXlbMl0KICAKICBzdWJqX2RhdGEgPC0gZGF0YSAlPiVzZWxlY3Qocm91bmQsIHBoYXNlLCByZXdhcmRfb2JzLCByZXdhcmRfdHJ1ZSwgbGFnLCBleGl0LCBzdGFydF9yZXdhcmQsIG5fdHJhdmVsX3N0ZXBzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmF2ZWxfa2V5LCBzdWJqZWN0SUQsIHRyaWFsX251bSwgc19udW0sIGNvcnJlY3Rfa2V5KSAlPiUgZ3JvdXBfYnkodHJpYWxfbnVtKSAlPiUKICAgIG11dGF0ZShwcmVzc19udW0gPSAxOm4oKSwgcm91bmQgPSBhcy5mYWN0b3Iocm91bmQpLCAKICAgICAgICAgICByZXBfbnVtYmVyID0gY2FzZV93aGVuKHRyaWFsX251bSA8IDcgfiAxLCBUUlVFIH4gMikpICU+JQogICAgbXV0YXRlKHBoYXNlID0gcmVwbGFjZShwaGFzZSwgcGhhc2UgPT0gIkhhcnZlc3QiLCAiSEFSVkVTVCIpKQoKICBzdWJqX2RhdGEgPC0gc3Vial9kYXRhICU+JSBncm91cF9ieSh0cmlhbF9udW0pICU+JSAKICAgIG11dGF0ZSh0cmF2ZWxfa2V5ID0gcmVwbGFjZSh0cmF2ZWxfa2V5LCB0cmF2ZWxfa2V5ID09ICIiLCBmaXJzdCh0cmF2ZWxfa2V5W3RyYXZlbF9rZXkgIT0gIiJdKSkpICU+JQogICAgbXV0YXRlKHRyYXZlbF9rZXlfY29uZCA9IGNhc2Vfd2hlbih0cmF2ZWxfa2V5ID09IHRyYXZlbF9rZXlfaGFyZCAgIH4gIkhBUkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmF2ZWxfa2V5ID09IHRyYXZlbF9rZXlfZWFzeSAgfiAiRUFTWSIpKSAlPiUKICAgIGZpbHRlcighaXMubmEodHJhdmVsX2tleV9jb25kKSkKfQoKIyBjbGVhbiBhbGwgdGhlIGRhdGEgYW5kIGJpbmQKZGF0YWxpc3QgPC0gbGlzdCgpCmZvciAoaSBpbiAxOjEwKXsKICBzdWJqX2RhdGEgPC0gZGF0YSAlPiUgZmlsdGVyKHNfbnVtID09IGkpCiAgc3Vial9kYXRhIDwtIGNsZWFuX3N1YmpfZGF0YShzdWJqX2RhdGEsIHRyYXZlbF9rZXlzKQogIHN1YmpfZGF0YSA8LSB1bmdyb3VwKHN1YmpfZGF0YSkKICBkYXRhbGlzdFtbaV1dIDwtIHN1YmpfZGF0YQp9CiNjZGF0YSA8LSBkby5jYWxsKHJiaW5kLGRhdGFsaXN0KQpjZGF0YSA8LSBiaW5kX3Jvd3MoZGF0YWxpc3QpCmBgYApgYGB7cn0KIyBtYWtlIGEgZnVuY3Rpb24gdG8gcGxvdCByZXdhcmQgb24gZWFjaCBnYW1lLi4uIApwbG90X3N1YmpfcmV3YXJkX3ZfcHJlc3MgPC0gZnVuY3Rpb24oc3Vial9kYXRhKXsKICAKICBzX251bSA8LSBzdWJqX2RhdGEkc19udW1bMV0KICAKICAjIHJld2FyZCBwbG90cyB3aGljaCBzaG93IHRoZSB0aHJlc2hvbGQuLi4gCiAgcmV3X3Bsb3QgPC0gZ2dwbG90KHN1YmpfZGF0YSwgYWVzKHggPSBwcmVzc19udW0sIHkgPSByZXdhcmRfb2JzLCBncm91cCA9IHJvdW5kKSkgICsKICAgICNnZW9tX3JlY3QoZGF0YSA9IHQxX2RhdGEsIGFlcyh4bWluID0gcHJlc3NfbnVtIC0gMC41LCB4bWF4ID0gcHJlc3NfbnVtICsgMC41LCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9IHJvdW5kKSkgKwogICAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBwaGFzZSkpICsgZmFjZXRfZ3JpZChuX3RyYXZlbF9zdGVwcyB+IHRyYXZlbF9rZXlfY29uZCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgeWxpbSgwLDExMCkgKyBnZ3RpdGxlKHBhc3RlKCJzdWJqOiAiLCBzX251bSkpCiAgCiAjIHBsb3RfYW4gPC0gYW5ub3RhdGVfZmlndXJlKHBsb3QsIHRvcCA9IHBhc3RlKCdzdWJqOiAnLCBzX251bSkpCiAgcGxvdChyZXdfcGxvdCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKfQpmb3IgKHMgaW4gMToyMil7CiAgc3Vial9kYXRhIDwtIGNkYXRhICU+JSBmaWx0ZXIoc19udW0gPT0gcykKICBwbG90X3N1YmpfcmV3YXJkX3ZfcHJlc3Moc3Vial9kYXRhKSAgCn0KYGBgCmBgYHtyfQpnZXRfdHJpYWxfZXhpdHMgPC0gZnVuY3Rpb24odGhkYXRhKXsKICAgICMgZ2V0IGhhcnZlc3QKICBsYXN0X3BoYXNlIDwtIGxhc3QodGhkYXRhJHBoYXNlKQogIAogICMgZ28gdGhyb3VnaCBkYXRhLi4gaWYgbGFzdCBwaGFzZSB3YXMgaGFydmVzdCwgcmVtb3ZlIHRoYXQgcm91bmQuLi4gCiAgaWYgKGxhc3RfcGhhc2UgPT0gIkhBUlZFU1QiKXsKICAgIGxhc3Rfcm91bmQgPC0gbGFzdCh0aGRhdGEkcm91bmQpCiAgICAjIGdldCB0aGUgbGFzdCByZXdhcmQgb3BzLi4uCiAgICBsYXN0X3Jld2FyZF9vYiA8LSBsYXN0KHRoZGF0YSRyZXdhcmRfb2JzWyFpcy5uYSh0aGRhdGEkcmV3YXJkX29icyldKQogICAgCiAgICAjaWYgKGxhc3RfcmV3YXJkX29iID4gOCl7CiAgICB0aGRhdGEgPC0gdGhkYXRhICU+JSBmaWx0ZXIocm91bmQgIT0gbGFzdF9yb3VuZCkKICAgICN9CiAgfQogIAogICMgbm93IHNlbGVjdCBoYXJ2ZXN0IGRhdGEKICB0aGRhdGEgPC0gdGhkYXRhICU+JSBmaWx0ZXIocGhhc2UgPT0gIkhBUlZFU1QiLCAhaXMubmEocmV3YXJkX29icykpICMgZmluZCBvdXQgd2h5IHJld2FyZF90cnVlIGhhcyBzbyBtYW55IC5uYQogIAogICMjIGdldCBlaXRoZXIgbGFzdCB0cnVlIHJld2FyZCBvYnNlcnZlZAogIHJldHVybl90YmwgPC0gdGhkYXRhICU+JSAKICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkocm91bmQpICU+JSAKICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZShzX251bSA9IGZpcnN0KHNfbnVtKSwgbGFzdF9yZXdhcmQgPSBsYXN0KHJld2FyZF9vYnMpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWFsX251bSA9IGZpcnN0KHRyaWFsX251bSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbl90cmF2ZWxfc3RlcHMgPSBmaXJzdChuX3RyYXZlbF9zdGVwcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhdmVsX2tleV9jb25kID0gZmlyc3QodHJhdmVsX2tleV9jb25kKSwKICAgICAgICAgICAgICAgICAgICAgICAgICByZXBfbnVtYmVyID0gZmlyc3QocmVwX251bWJlcikpICU+JSB1bmdyb3VwKCkKICByZXR1cm4ocmV0dXJuX3RibCkKfQoKI3NkYXRhICU+JSBncm91cF9ieSh0cmlhbF9udW0pICU+JQojICBkbyhnZXRfdHJpYWxfZXhpdHMoLikpCgpleGl0X2RhdGEgPC0gY2RhdGEgJT4lIGdyb3VwX2J5KHNfbnVtLCB0cmlhbF9udW0pICU+JQogIGRvKGdldF90cmlhbF9leGl0cyguKSkgJT4lIHVuZ3JvdXAoKSAlPiUgbXV0YXRlKHN1YmogPSBhcy5mYWN0b3Ioc19udW0pKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKZXhpdF9kYXRhIDwtIGV4aXRfZGF0YSAlPiUgbXV0YXRlKHJvdW5kX251bSA9IGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHJvdW5kKSkpCmZvciAocyBpbiAxOjIyKXsKICBwIDwtIGdncGxvdChleGl0X2RhdGEgJT4lIGZpbHRlcihzX251bSA9PSBzKSwgYWVzKHggPSByb3VuZF9udW0sIHkgPSBsYXN0X3Jld2FyZCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKwogIGZhY2V0X2dyaWQobl90cmF2ZWxfc3RlcHMgfiB0cmF2ZWxfa2V5X2NvbmQpICsgdGhlbWVfbWluaW1hbCgpICArIHlsaW0oMCwxMDApICsgeWxhYignbGFzdCByZXdhcmQgY29sbGVjdGVkJykgKyB4bGFiKCdoYXJ2ZXN0IG51bWJlcicpCiAgCiAgI3Bsb3QocCkKICAjZ2dhcnJhbmdlKHApCiAgYSA8LSBhbm5vdGF0ZV9maWd1cmUocCwgcmlnaHQgPSAiIyB0cmF2ZWwgc3RlcHMiLCB0b3AgPSAidHJhdmVsIHN0ZXAgZGlmZmljdWx0eSIsIGZpZy5sYWIgPSBwYXN0ZSgnc3ViajogJyAsIHMpKQogIHBsb3QoYSkKfQoKYGBgCgpgYGB7cn0KIyBkbyBzb21lIGFnZ3JlZ2F0aW5nIG92ZXIgZXhpdCB0aHJlc2hvbGRzLi4uIAojIGp1c3QgZ2V0IHRoZSBtZWFuIGZvciBlYWNoIHN1YmplY3QgZm9yIGVhY2ggdGltZXBvaW50LCBjb2xsYXBzZSBhY2Nyb3NzIHJlcCBudW1iZXIuLi4KbW5fZXhpdCA8LSBleGl0X2RhdGEgJT4lIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kKSAlPiUKICBzdW1tYXJpc2UocmVwX2V4aXRfdGhyZXNoID0gbWVhbihsYXN0X3Jld2FyZCksIHRyaWFsX251bSA9IG1lYW4odHJpYWxfbnVtKSkgJT4lIAogIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kKSAlPiUKICBzdW1tYXJpc2UoZXhpdF90aHJlc2ggPSBtZWFuKHJlcF9leGl0X3RocmVzaCksIHRyaWFsX251bSA9IG1lYW4odHJpYWxfbnVtKSkgJT4lCiAgbXV0YXRlKHN1YmogPSBhcy5mYWN0b3Ioc19udW0pKSAlPiUgdW5ncm91cCgpCgojIG5vdyBqdXN0IHBsb3QgdGhpcyBmb3IgZWFjaCBzdWJqZWN0IC0tIGRyYXcgbGluZXMgdG8gc2hvdyBlYXN5IC0gaGFyZCBlZmZlY3QKZ2dwbG90KG1uX2V4aXQsIGFlcyh4ID0gdHJhdmVsX2tleV9jb25kLCB5ID0gZXhpdF90aHJlc2gpKSArIGdlb21fZG90cGxvdChiaW5heGlzID0gJ3knLCBhZXMoZmlsbCA9IHN1YmopLCBkb3RzaXplID0gMS4yKSArIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzdWJqLCBjb2xvciA9IHN1YmopLCBzaXplID0gMS4yKSArCiAgZmFjZXRfZ3JpZCgufm5fdHJhdmVsX3N0ZXBzKSArIHRoZW1lX21pbmltYWwoKSArIGxhYnMoeSA9ICdNZWFuIExhc3QgUmV3YXJkIENvbGxlY3RlZCcsIHggPSAnVHJhdmVsIFNlcXVlbmNlJywgc3VidGl0bGUgPSAnIyBUcmF2ZWwgUHJlc3NlcycpICN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpnZ3Bsb3QobW5fZXhpdCwgYWVzKHggPSBmYWN0b3Iobl90cmF2ZWxfc3RlcHMpLCB5ID0gZXhpdF90aHJlc2gpKSArCiAgZ2VvbV9kb3RwbG90KGJpbmF4aXMgPSAneScsIGFlcyhmaWxsID0gc3ViaiksIGRvdHNpemUgPSAxLjIpICsgCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHN1YmosIGNvbG9yID0gc3ViaiksIHNpemUgPSAxLjIpICsKICBmYWNldF9ncmlkKC5+dHJhdmVsX2tleV9jb25kKSArIAogIHRoZW1lX21pbmltYWwoKSArIAogIGxhYnMoeSA9ICdNZWFuIExhc3QgUmV3YXJkIENvbGxlY3RlZCcsIHggPSAnVHJhdmVsIEtleSBDb25kaXRpb24nLCBzdWJ0aXRsZSA9ICcjIFRyYXZlbCBQcmVzc2VzJykgCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYApgYGB7cn0KIyBwbG90IHRoZSBtZWFucyBmb3IgZWFjaCBvZiB0aGVzZS4uLgpnbW5fZXhpdCA8LSBtbl9leGl0ICU+JSBncm91cF9ieShuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kKSAlPiUgc3VtbWFyaXNlKGdtX3RocmVzaCA9IG1lYW4oZXhpdF90aHJlc2gpLCBnc2RfdGhyZXNoID0gc2QoZXhpdF90aHJlc2gpL3NxcnQobigpKSkKCmdncGxvdChnbW5fZXhpdCwgYWVzKHggPSBmYWN0b3Iobl90cmF2ZWxfc3RlcHMpLCB5ID0gZ21fdGhyZXNoLCBjb2xvciA9IHRyYXZlbF9rZXlfY29uZCkpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gdHJhdmVsX2tleV9jb25kKSwgc2l6ZSA9IDIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZ21fdGhyZXNoIC0gZ3NkX3RocmVzaCwgeW1heCA9IGdtX3RocmVzaCtnc2RfdGhyZXNoKSwgd2lkdGggPSAuMSwgc2l6ZSA9IDIpICsgCmdlb21fcG9pbnQoc2l6ZSA9IDQpICsgeWxhYignZ3JvdXAgbWVhbiBleGl0IHRocmVzaG9sZCcpICsgeGxhYignIyB0cmF2ZWwgc3RlcHMnKSArIGxhYnMoY29sb3IgPSAndHJhdmVsIGVmZm9ydCcpICsgdGhlbWVfbWluaW1hbCgpCgpgYGAKCmBgYHtyfQoKbGlicmFyeShvcHRpbXgpCmxpYnJhcnkobG1lclRlc3QpCmV4aXRfbW9kZWwgPC0gbG1lcihsYXN0X3Jld2FyZCB+IG5fdHJhdmVsX3N0ZXBzICsgdHJhdmVsX2tleV9jb25kICArICgxICArIG5fdHJhdmVsX3N0ZXBzICsgdHJhdmVsX2tleV9jb25kIHxzdWJqKSwgZGF0YSA9IGV4aXRfZGF0YSwgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSJvcHRpbXgiLG9wdEN0cmw9bGlzdChtZXRob2Q9J25sbWluYicpKSkKc3VtbWFyeShleGl0X21vZGVsKQogICAgICAgICAgICAgICAgICAgCmBgYApgYGB7cn0KbGlicmFyeShicm9vbS5taXhlZCkKdGQgPC0gdGlkeShleGl0X21vZGVsLCBjb25mLmludCA9IFRSVUUpCnRkc29tZSA8LSB0ZCAlPiUgZmlsdGVyKHRlcm0gPT0gJ25fdHJhdmVsX3N0ZXBzJyB8IHRlcm0gPT0gJ3RyYXZlbF9rZXlfY29uZEhBUkQnKQoKdGRzb21lIDwtIHRkc29tZSAlPiUgbXV0YXRlKHBhcmFtZXRlciA9IGNhc2Vfd2hlbih0ZXJtID09ICduX3RyYXZlbF9zdGVwcycgfiAndHJhdmVsIHN0ZXAnLCB0ZXJtID09ICd0cmF2ZWxfa2V5X2NvbmRIQVJEJyB+ICd0cmF2ZWwgZWZmb3J0IGNvbmQnKSkKCmdncGxvdCh0ZHNvbWUsIGFlcyhlc3RpbWF0ZSxwYXJhbWV0ZXIsY29sb3IgPSBwYXJhbWV0ZXIpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICArCmdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gY29uZi5sb3csIHhtYXggPSBjb25mLmhpZ2gpLCBzaXplID0gMS4yKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyB0aGVtZV9taW5pbWFsKCkgKyB5bGFiKCdmaXhlZCBlZmZlY3QnKSArIHhsYWIoJ2VzdGltYXRlICgjIHBvaW50cyknKSArIGdndGl0bGUoJ2xpbmVhciBtaXhlZCBlZmZlY3RzIG1vZGVsIC0gZWZmZWN0IG9uIGV4aXQgdGhyZXNob2xkJykgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IC41KSkKYGBgCgpgYGB7cn0KIyByZWFjdGlvbiB0aW1lcy4uLiAKCgojIyBhIGJpdCBtb3JlIHNlbnNpYmxlLi4uIApsYWdfZGF0YSA8LSBjZGF0YSAlPiUgc2VsZWN0KHNfbnVtLCByZXBfbnVtYmVyLCB0cmF2ZWxfa2V5X2NvbmQsIG5fdHJhdmVsX3N0ZXBzLCBwaGFzZSwgdHJpYWxfbnVtLCBsYWcsIGNvcnJlY3Rfa2V5LCByb3VuZCwgdHJpYWxfbnVtKSAlPiUgbXV0YXRlKGxvZ19sYWcgPSBsb2cobGFnKSkgJT4lIGdyb3VwX2J5KHNfbnVtLCB0cmlhbF9udW0sIHJvdW5kLCBwaGFzZSkgJT4lIHNsaWNlKC0xKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoc3ViaiA9IGFzLmZhY3RvcihzX251bSkpCgpnZ3Bsb3QobGFnX2RhdGEsIGFlcyh4PWxhZykpICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCkgKyB4bGltKDUwLDMwMCkgKyBmYWNldF93cmFwKCB+IHNfbnVtKQoKI2dncGxvdChsYWdfZGF0YSwgYWVzKHg9bG9nX2xhZykpICArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gLjAxKSArIGZhY2V0X3dyYXAoIH4gc19udW0pCgpmaWx0X2xhZyA8LSBsYWdfZGF0YSAlPiUgZ3JvdXBfYnkoc19udW0pICU+JSBmaWx0ZXIobG9nX2xhZyA8IChtZWFuKGxvZ19sYWcpICsgMypzZChsb2dfbGFnKSkgLCBsb2dfbGFnID4gKG1lYW4obG9nX2xhZykgLSAzKnNkKGxvZ19sYWcpKSkgJT4lIHVuZ3JvdXAoKQoKZ2dwbG90KGZpbHRfbGFnLCBhZXMoeD1sYWcpKSArIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMTApICArIGZhY2V0X3dyYXAofnNfbnVtKSArIHhsaW0oNTAsMzUwKQoKZ2dwbG90KGZpbHRfbGFnLCBhZXMoeD1sb2dfbGFnKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMikgKyBmYWNldF93cmFwKH5zX251bSkKCgoKYGBgCmBgYHtyfQojIyB3aXRoIGEgcnVuLCBwbG90IHRoZSBtZWFuIGxhZyAKcm91bmRfZmlsdF9sYWcgPC0gZmlsdF9sYWcgJT4lIAogIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kLCByb3VuZCwgcGhhc2UpICU+JQogIHN1bW1hcmlzZSh0cmlhbF9udW0gPSBmaXJzdCh0cmlhbF9udW0pLCBtZWFuX2xhZyA9IG1lYW4obGFnKSwgbWVhbl9sb2dfbGFnID0gbWVhbihsb2dfbGFnKSkgJT4lIG11dGF0ZShyb3VuZF9udW0gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3Rlcihyb3VuZCkpKQoKIyBwbG90IG1lYW4gbGFnIGFzIGEgZnVuY3Rpb24gb2Ygcm91bmQgbnVtYmVyCmxhZ19ieV9yb3VuZCA8LSByb3VuZF9maWx0X2xhZyAlPiUgZ3JvdXBfYnkoc19udW0sIHJvdW5kX251bSkgJT4lIHN1bW1hcmlzZShtZWFuX2xhZyA9IG1lYW4obWVhbl9sYWcpKQoKZ2dwbG90KGxhZ19ieV9yb3VuZCwgYWVzKHg9IHJvdW5kX251bSwgeSA9IG1lYW5fbGFnKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArIGZhY2V0X3dyYXAofnNfbnVtKQoKdHJpYWxfZmlsdF9sYWcgPC0gcm91bmRfZmlsdF9sYWcgJT4lIAogIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kLCBwaGFzZSkgJT4lCiAgc3VtbWFyaXNlKHRyaWFsX251bSA9IGZpcnN0KHRyaWFsX251bSksIAogICAgICAgICAgICBtZWFuX2xhZyA9IG1lYW4obWVhbl9sYWcpLCAKICAgICAgICAgICAgbWVhbl9sb2dfbGFnID0gbWVhbihtZWFuX2xvZ19sYWcpKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoc19udW0gPSBhcy5mYWN0b3Ioc19udW0pKQoKZ2dwbG90KHRyaWFsX2ZpbHRfbGFnLCAKICAgICAgIGFlcyh4ID0gZmFjdG9yKG5fdHJhdmVsX3N0ZXBzKSwgeSA9IG1lYW5fbGFnLCBmaWxsID0gc19udW0pKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc19udW0pLCBzaXplID0gMikrIAogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzX251bSwgY29sb3IgPSBzX251bSksIHNpemUgPSAxLjIpICsKICBmYWNldF9ncmlkKHBoYXNlIH4gdHJhdmVsX2tleV9jb25kKSArIHRoZW1lX21pbmltYWwoKQoKZ2dwbG90KHRyaWFsX2ZpbHRfbGFnLCAKICAgICAgIGFlcyh4ID0gdHJhdmVsX2tleV9jb25kLCB5ID0gbWVhbl9sYWcsIGZpbGwgPSBzX251bSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBzX251bSksIHNpemUgPSAyKSsgCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNfbnVtLCBjb2xvciA9IHNfbnVtKSwgc2l6ZSA9IDEuMikgKwogIGZhY2V0X2dyaWQocGhhc2UgfiBuX3RyYXZlbF9zdGVwcykgKyB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KCgpncm91cF9sYWcgPC0gdHJpYWxfZmlsdF9sYWcgJT4lIGdyb3VwX2J5KG5fdHJhdmVsX3N0ZXBzLCB0cmF2ZWxfa2V5X2NvbmQsIHBoYXNlKSAlPiUgc3VtbWFyaXNlKGdtX2xhZyA9IG1lYW4obWVhbl9sYWcpLCBnbWxfbGFnID0gbWVhbihtZWFuX2xvZ19sYWcpKSAlPiUgdW5ncm91cCgpCgpnZ3Bsb3QoZ3JvdXBfbGFnLCBhZXMoeCA9IGZhY3RvcihuX3RyYXZlbF9zdGVwcyksIHkgPSBnbV9sYWcsIGNvbG9yID0gdHJhdmVsX2tleV9jb25kKSkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSB0cmF2ZWxfa2V5X2NvbmQpLCBzaXplID0gMikgKyBmYWNldF93cmFwKH5waGFzZSkgKyBnZW9tX3BvaW50KHNpemUgPSAyKQogIyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZ21fdGhyZXNoIC0gZ3NkX3RocmVzaCwgeW1heCA9IGdtX3RocmVzaCtnc2RfdGhyZXNoKSwgd2lkdGggPSAuMSwgc2l6ZSA9IDIpICsgCiNnZW9tX3BvaW50KHNpemUgPSA0KSArIHlsYWIoJ2dyb3VwIG1lYW4gZXhpdCB0aHJlc2hvbGQnKSArIHhsYWIoJyMgdHJhdmVsIHN0ZXBzJykgKyBsYWJzKGNvbG9yID0gJ3RyYXZlbCBlZmZvcnQnKSArIHRoZW1lX21pbmltYWwoKQoKCgpgYGAKYGBge3J9CmhhcnZlc3RfbGFnIDwtIGZpbHRfbGFnICU+JSB1bmdyb3VwKCkgJT4lIGZpbHRlcihwaGFzZSA9PSAiSEFSVkVTVCIpCmhsX21vZGVsIDwtIGxtZXIobG9nX2xhZyB+IHRyaWFsX251bSArIG5fdHJhdmVsX3N0ZXBzICsgdHJhdmVsX2tleV9jb25kICArICgxICsgdHJpYWxfbnVtICsgbl90cmF2ZWxfc3RlcHMgKyB0cmF2ZWxfa2V5X2NvbmQgfHN1YmopLCBkYXRhID0gaGFydmVzdF9sYWcsIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSJvcHRpbXgiLG9wdEN0cmw9bGlzdChtZXRob2Q9J25sbWluYicpKSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShobF9tb2RlbCkKYGBgCgo=
=======
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCmBgYHtyfQ0Kc2V0d2QoIkM6L1VzZXJzL2VydXNzZWsvZm9yYWdlX2pzcC9hbmFseXNpcyIpDQpybShsaXN0ID0gbHMoKSkNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh6b28pDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkoUmNwcFJvbGwpDQpsaWJyYXJ5KGtuaXRyKQ0KYGBgDQoNCmBgYHtyfQ0KZGF0YSA8LSByZWFkLmNzdignZGF0YVxccnVuNF9kYXRhLmNzdicpDQpoZWFkKGRhdGEpDQpkYXRhIDwtIGRhdGEgJT4lIHVuZ3JvdXAoKSAlPiUgYmluZF9jb2xzKHNfbnVtID0gZ3JvdXBfaW5kaWNlcyguLCBzdWJqZWN0SUQpKQ0KZGF0YSA8LSBkYXRhICU+JSBtdXRhdGUoc3ViaiA9IGZhY3RvcihzX251bSkpDQpgYGANCg0KYGBge3J9DQp0cmF2ZWxfa2V5cyA9IGRhdGEgJT4lIHVuZ3JvdXAoKSAlPiUgc2VsZWN0KHRyYXZlbF9rZXkpICU+JSB1bmlxdWUoKQ0KY2xlYW5fc3Vial9kYXRhIDwtIGZ1bmN0aW9uKHN1YmpfZGF0YSwgdHJhdmVsX2tleXMpew0KICB0cmF2ZWxfa2V5X2hhcmQgPSB0cmF2ZWxfa2V5cyR0cmF2ZWxfa2V5WzFdDQogIHRyYXZlbF9rZXlfZWFzeSA9IHRyYXZlbF9rZXlzJHRyYXZlbF9rZXlbMl0NCiAgDQogIHN1YmpfZGF0YSA8LSBkYXRhICU+JXNlbGVjdChyb3VuZCwgcGhhc2UsIHJld2FyZF9vYnMsIHJld2FyZF90cnVlLCBsYWcsIGV4aXQsIHN0YXJ0X3Jld2FyZCwgbl90cmF2ZWxfc3RlcHMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmF2ZWxfa2V5LCBzdWJqZWN0SUQsIHRyaWFsX251bSwgc19udW0sIGNvcnJlY3Rfa2V5KSAlPiUgZ3JvdXBfYnkodHJpYWxfbnVtKSAlPiUNCiAgICBtdXRhdGUocHJlc3NfbnVtID0gMTpuKCksIHJvdW5kID0gYXMuZmFjdG9yKHJvdW5kKSwgDQogICAgICAgICAgIHJlcF9udW1iZXIgPSBjYXNlX3doZW4odHJpYWxfbnVtIDwgNyB+IDEsIFRSVUUgfiAyKSkgJT4lDQogICAgbXV0YXRlKHBoYXNlID0gcmVwbGFjZShwaGFzZSwgcGhhc2UgPT0gIkhhcnZlc3QiLCAiSEFSVkVTVCIpKQ0KDQogIHN1YmpfZGF0YSA8LSBzdWJqX2RhdGEgJT4lIGdyb3VwX2J5KHRyaWFsX251bSkgJT4lIA0KICAgIG11dGF0ZSh0cmF2ZWxfa2V5ID0gcmVwbGFjZSh0cmF2ZWxfa2V5LCB0cmF2ZWxfa2V5ID09ICIiLCBmaXJzdCh0cmF2ZWxfa2V5W3RyYXZlbF9rZXkgIT0gIiJdKSkpICU+JQ0KICAgIG11dGF0ZSh0cmF2ZWxfa2V5X2NvbmQgPSBjYXNlX3doZW4odHJhdmVsX2tleSA9PSB0cmF2ZWxfa2V5X2hhcmQgICB+ICJIQVJEIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYXZlbF9rZXkgPT0gdHJhdmVsX2tleV9lYXN5ICB+ICJFQVNZIikpICU+JQ0KICAgIGZpbHRlcighaXMubmEodHJhdmVsX2tleV9jb25kKSkNCn0NCg0KIyBjbGVhbiBhbGwgdGhlIGRhdGEgYW5kIGJpbmQNCmRhdGFsaXN0IDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6MTApew0KICBzdWJqX2RhdGEgPC0gZGF0YSAlPiUgZmlsdGVyKHNfbnVtID09IGkpDQogIHN1YmpfZGF0YSA8LSBjbGVhbl9zdWJqX2RhdGEoc3Vial9kYXRhLCB0cmF2ZWxfa2V5cykNCiAgc3Vial9kYXRhIDwtIHVuZ3JvdXAoc3Vial9kYXRhKQ0KICBkYXRhbGlzdFtbaV1dIDwtIHN1YmpfZGF0YQ0KfQ0KI2NkYXRhIDwtIGRvLmNhbGwocmJpbmQsZGF0YWxpc3QpDQpjZGF0YSA8LSBiaW5kX3Jvd3MoZGF0YWxpc3QpDQpgYGANCmBgYHtyfQ0KIyBtYWtlIGEgZnVuY3Rpb24gdG8gcGxvdCByZXdhcmQgb24gZWFjaCBnYW1lLi4uIA0KcGxvdF9zdWJqX3Jld2FyZF92X3ByZXNzIDwtIGZ1bmN0aW9uKHN1YmpfZGF0YSl7DQogIA0KICBzX251bSA8LSBzdWJqX2RhdGEkc19udW1bMV0NCiAgDQogICMgcmV3YXJkIHBsb3RzIHdoaWNoIHNob3cgdGhlIHRocmVzaG9sZC4uLiANCiAgcmV3X3Bsb3QgPC0gZ2dwbG90KHN1YmpfZGF0YSwgYWVzKHggPSBwcmVzc19udW0sIHkgPSByZXdhcmRfb2JzLCBncm91cCA9IHJvdW5kKSkgICsNCiAgICAjZ2VvbV9yZWN0KGRhdGEgPSB0MV9kYXRhLCBhZXMoeG1pbiA9IHByZXNzX251bSAtIDAuNSwgeG1heCA9IHByZXNzX251bSArIDAuNSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSByb3VuZCkpICsNCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHBoYXNlKSkgKyBmYWNldF9ncmlkKG5fdHJhdmVsX3N0ZXBzIH4gdHJhdmVsX2tleV9jb25kKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyB5bGltKDAsMTEwKSArIGdndGl0bGUocGFzdGUoInN1Ymo6ICIsIHNfbnVtKSkNCiAgDQogIyBwbG90X2FuIDwtIGFubm90YXRlX2ZpZ3VyZShwbG90LCB0b3AgPSBwYXN0ZSgnc3ViajogJywgc19udW0pKQ0KICBwbG90KHJld19wbG90KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCn0NCmZvciAocyBpbiAxOjIyKXsNCiAgc3Vial9kYXRhIDwtIGNkYXRhICU+JSBmaWx0ZXIoc19udW0gPT0gcykNCiAgcGxvdF9zdWJqX3Jld2FyZF92X3ByZXNzKHN1YmpfZGF0YSkgIA0KfQ0KYGBgDQpgYGB7cn0NCmdldF90cmlhbF9leGl0cyA8LSBmdW5jdGlvbih0aGRhdGEpew0KICAgICMgZ2V0IGhhcnZlc3QNCiAgbGFzdF9waGFzZSA8LSBsYXN0KHRoZGF0YSRwaGFzZSkNCiAgDQogICMgZ28gdGhyb3VnaCBkYXRhLi4gaWYgbGFzdCBwaGFzZSB3YXMgaGFydmVzdCwgcmVtb3ZlIHRoYXQgcm91bmQuLi4gDQogIGlmIChsYXN0X3BoYXNlID09ICJIQVJWRVNUIil7DQogICAgbGFzdF9yb3VuZCA8LSBsYXN0KHRoZGF0YSRyb3VuZCkNCiAgICAjIGdldCB0aGUgbGFzdCByZXdhcmQgb3BzLi4uDQogICAgbGFzdF9yZXdhcmRfb2IgPC0gbGFzdCh0aGRhdGEkcmV3YXJkX29ic1shaXMubmEodGhkYXRhJHJld2FyZF9vYnMpXSkNCiAgICANCiAgICAjaWYgKGxhc3RfcmV3YXJkX29iID4gOCl7DQogICAgdGhkYXRhIDwtIHRoZGF0YSAlPiUgZmlsdGVyKHJvdW5kICE9IGxhc3Rfcm91bmQpDQogICAgI30NCiAgfQ0KICANCiAgIyBub3cgc2VsZWN0IGhhcnZlc3QgZGF0YQ0KICB0aGRhdGEgPC0gdGhkYXRhICU+JSBmaWx0ZXIocGhhc2UgPT0gIkhBUlZFU1QiLCAhaXMubmEocmV3YXJkX29icykpICMgZmluZCBvdXQgd2h5IHJld2FyZF90cnVlIGhhcyBzbyBtYW55IC5uYQ0KICANCiAgIyMgZ2V0IGVpdGhlciBsYXN0IHRydWUgcmV3YXJkIG9ic2VydmVkDQogIHJldHVybl90YmwgPC0gdGhkYXRhICU+JSANCiAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHJvdW5kKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKHNfbnVtID0gZmlyc3Qoc19udW0pLCBsYXN0X3Jld2FyZCA9IGxhc3QocmV3YXJkX29icyksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWFsX251bSA9IGZpcnN0KHRyaWFsX251bSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIG5fdHJhdmVsX3N0ZXBzID0gZmlyc3Qobl90cmF2ZWxfc3RlcHMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmF2ZWxfa2V5X2NvbmQgPSBmaXJzdCh0cmF2ZWxfa2V5X2NvbmQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICByZXBfbnVtYmVyID0gZmlyc3QocmVwX251bWJlcikpICU+JSB1bmdyb3VwKCkNCiAgcmV0dXJuKHJldHVybl90YmwpDQp9DQoNCiNzZGF0YSAlPiUgZ3JvdXBfYnkodHJpYWxfbnVtKSAlPiUNCiMgIGRvKGdldF90cmlhbF9leGl0cyguKSkNCg0KZXhpdF9kYXRhIDwtIGNkYXRhICU+JSBncm91cF9ieShzX251bSwgdHJpYWxfbnVtKSAlPiUNCiAgZG8oZ2V0X3RyaWFsX2V4aXRzKC4pKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoc3ViaiA9IGFzLmZhY3RvcihzX251bSkpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGdncHVicikNCmV4aXRfZGF0YSA8LSBleGl0X2RhdGEgJT4lIG11dGF0ZShyb3VuZF9udW0gPSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3Rlcihyb3VuZCkpKQ0KZm9yIChzIGluIDE6MjIpew0KICBwIDwtIGdncGxvdChleGl0X2RhdGEgJT4lIGZpbHRlcihzX251bSA9PSBzKSwgYWVzKHggPSByb3VuZF9udW0sIHkgPSBsYXN0X3Jld2FyZCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKCkgKw0KICBmYWNldF9ncmlkKG5fdHJhdmVsX3N0ZXBzIH4gdHJhdmVsX2tleV9jb25kKSArIHRoZW1lX21pbmltYWwoKSAgKyB5bGltKDAsMTAwKSArIHlsYWIoJ2xhc3QgcmV3YXJkIGNvbGxlY3RlZCcpICsgeGxhYignaGFydmVzdCBudW1iZXInKQ0KICANCiAgI3Bsb3QocCkNCiAgI2dnYXJyYW5nZShwKQ0KICBhIDwtIGFubm90YXRlX2ZpZ3VyZShwLCByaWdodCA9ICIjIHRyYXZlbCBzdGVwcyIsIHRvcCA9ICJ0cmF2ZWwgc3RlcCBkaWZmaWN1bHR5IiwgZmlnLmxhYiA9IHBhc3RlKCdzdWJqOiAnICwgcykpDQogIHBsb3QoYSkNCn0NCg0KYGBgDQoNCmBgYHtyfQ0KIyBkbyBzb21lIGFnZ3JlZ2F0aW5nIG92ZXIgZXhpdCB0aHJlc2hvbGRzLi4uIA0KIyBqdXN0IGdldCB0aGUgbWVhbiBmb3IgZWFjaCBzdWJqZWN0IGZvciBlYWNoIHRpbWVwb2ludCwgY29sbGFwc2UgYWNjcm9zcyByZXAgbnVtYmVyLi4uDQptbl9leGl0IDwtIGV4aXRfZGF0YSAlPiUgZ3JvdXBfYnkoc19udW0sIG5fdHJhdmVsX3N0ZXBzLCB0cmF2ZWxfa2V5X2NvbmQpICU+JQ0KICBzdW1tYXJpc2UocmVwX2V4aXRfdGhyZXNoID0gbWVhbihsYXN0X3Jld2FyZCksIHRyaWFsX251bSA9IG1lYW4odHJpYWxfbnVtKSkgJT4lIA0KICBncm91cF9ieShzX251bSwgbl90cmF2ZWxfc3RlcHMsIHRyYXZlbF9rZXlfY29uZCkgJT4lDQogIHN1bW1hcmlzZShleGl0X3RocmVzaCA9IG1lYW4ocmVwX2V4aXRfdGhyZXNoKSwgdHJpYWxfbnVtID0gbWVhbih0cmlhbF9udW0pKSAlPiUNCiAgbXV0YXRlKHN1YmogPSBhcy5mYWN0b3Ioc19udW0pKSAlPiUgdW5ncm91cCgpDQoNCiMgbm93IGp1c3QgcGxvdCB0aGlzIGZvciBlYWNoIHN1YmplY3QgLS0gZHJhdyBsaW5lcyB0byBzaG93IGVhc3kgLSBoYXJkIGVmZmVjdA0KZ2dwbG90KG1uX2V4aXQsIGFlcyh4ID0gdHJhdmVsX2tleV9jb25kLCB5ID0gZXhpdF90aHJlc2gpKSArIGdlb21fZG90cGxvdChiaW5heGlzID0gJ3knLCBhZXMoZmlsbCA9IHN1YmopLCBkb3RzaXplID0gMS4yKSArIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzdWJqLCBjb2xvciA9IHN1YmopLCBzaXplID0gMS4yKSArDQogIGZhY2V0X2dyaWQoLn5uX3RyYXZlbF9zdGVwcykgKyB0aGVtZV9taW5pbWFsKCkgKyBsYWJzKHkgPSAnTWVhbiBMYXN0IFJld2FyZCBDb2xsZWN0ZWQnLCB4ID0gJ1RyYXZlbCBTZXF1ZW5jZScsIHN1YnRpdGxlID0gJyMgVHJhdmVsIFByZXNzZXMnKSAjdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpnZ3Bsb3QobW5fZXhpdCwgYWVzKHggPSBmYWN0b3Iobl90cmF2ZWxfc3RlcHMpLCB5ID0gZXhpdF90aHJlc2gpKSArDQogIGdlb21fZG90cGxvdChiaW5heGlzID0gJ3knLCBhZXMoZmlsbCA9IHN1YmopLCBkb3RzaXplID0gMS4yKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gc3ViaiwgY29sb3IgPSBzdWJqKSwgc2l6ZSA9IDEuMikgKw0KICBmYWNldF9ncmlkKC5+dHJhdmVsX2tleV9jb25kKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgbGFicyh5ID0gJ01lYW4gTGFzdCBSZXdhcmQgQ29sbGVjdGVkJywgeCA9ICdUcmF2ZWwgS2V5IENvbmRpdGlvbicsIHN1YnRpdGxlID0gJyMgVHJhdmVsIFByZXNzZXMnKSANCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KYGBgDQpgYGB7cn0NCiMgcGxvdCB0aGUgbWVhbnMgZm9yIGVhY2ggb2YgdGhlc2UuLi4NCmdtbl9leGl0IDwtIG1uX2V4aXQgJT4lIGdyb3VwX2J5KG5fdHJhdmVsX3N0ZXBzLCB0cmF2ZWxfa2V5X2NvbmQpICU+JSBzdW1tYXJpc2UoZ21fdGhyZXNoID0gbWVhbihleGl0X3RocmVzaCksIGdzZF90aHJlc2ggPSBzZChleGl0X3RocmVzaCkvc3FydChuKCkpKQ0KDQpnZ3Bsb3QoZ21uX2V4aXQsIGFlcyh4ID0gZmFjdG9yKG5fdHJhdmVsX3N0ZXBzKSwgeSA9IGdtX3RocmVzaCwgY29sb3IgPSB0cmF2ZWxfa2V5X2NvbmQpKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSB0cmF2ZWxfa2V5X2NvbmQpLCBzaXplID0gMikgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZ21fdGhyZXNoIC0gZ3NkX3RocmVzaCwgeW1heCA9IGdtX3RocmVzaCtnc2RfdGhyZXNoKSwgd2lkdGggPSAuMSwgc2l6ZSA9IDIpICsgDQpnZW9tX3BvaW50KHNpemUgPSA0KSArIHlsYWIoJ2dyb3VwIG1lYW4gZXhpdCB0aHJlc2hvbGQnKSArIHhsYWIoJyMgdHJhdmVsIHN0ZXBzJykgKyBsYWJzKGNvbG9yID0gJ3RyYXZlbCBlZmZvcnQnKSArIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KYGBge3J9DQoNCmxpYnJhcnkobG1lclRlc3QpDQpleGl0X21vZGVsIDwtIGxtZXIobGFzdF9yZXdhcmQgfiBuX3RyYXZlbF9zdGVwcyArIHRyYXZlbF9rZXlfY29uZCAgKyAoMSAgKyBuX3RyYXZlbF9zdGVwcyArIHRyYXZlbF9rZXlfY29uZCB8c3ViaiksIGRhdGEgPSBleGl0X2RhdGEsICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0ib3B0aW14IixvcHRDdHJsPWxpc3QobWV0aG9kPSdubG1pbmInKSkpDQpzdW1tYXJ5KGV4aXRfbW9kZWwpDQogICAgICAgICAgICAgICAgICAgDQpgYGANCmBgYHtyfQ0KdGQgPC0gdGlkeShleGl0X21vZGVsLCBjb25mLmludCA9IFRSVUUpDQp0ZHNvbWUgPC0gdGQgJT4lIGZpbHRlcih0ZXJtID09ICduX3RyYXZlbF9zdGVwcycgfCB0ZXJtID09ICd0cmF2ZWxfa2V5X2NvbmRIQVJEJykNCg0KdGRzb21lIDwtIHRkc29tZSAlPiUgbXV0YXRlKHBhcmFtZXRlciA9IGNhc2Vfd2hlbih0ZXJtID09ICduX3RyYXZlbF9zdGVwcycgfiAndHJhdmVsIHN0ZXAnLCB0ZXJtID09ICd0cmF2ZWxfa2V5X2NvbmRIQVJEJyB+ICd0cmF2ZWwgZWZmb3J0IGNvbmQnKSkNCg0KZ2dwbG90KHRkc29tZSwgYWVzKGVzdGltYXRlLHBhcmFtZXRlcixjb2xvciA9IHBhcmFtZXRlcikpICsgDQogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICArDQpnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IGNvbmYubG93LCB4bWF4ID0gY29uZi5oaWdoKSwgc2l6ZSA9IDEuMikgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgdGhlbWVfbWluaW1hbCgpICsgeWxhYignZml4ZWQgZWZmZWN0JykgKyB4bGFiKCdlc3RpbWF0ZSAoIyBwb2ludHMpJykgKyBnZ3RpdGxlKCdsaW5lYXIgbWl4ZWQgZWZmZWN0cyBtb2RlbCAtIGVmZmVjdCBvbiBleGl0IHRocmVzaG9sZCcpICsgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAuNSkpDQpgYGANCg0KYGBge3J9DQojIHJlYWN0aW9uIHRpbWVzLi4uIA0KDQoNCiMjIGEgYml0IG1vcmUgc2Vuc2libGUuLi4gDQpsYWdfZGF0YSA8LSBjZGF0YSAlPiUgc2VsZWN0KHNfbnVtLCByZXBfbnVtYmVyLCB0cmF2ZWxfa2V5X2NvbmQsIG5fdHJhdmVsX3N0ZXBzLCBwaGFzZSwgdHJpYWxfbnVtLCBsYWcsIGNvcnJlY3Rfa2V5LCByb3VuZCwgdHJpYWxfbnVtKSAlPiUgbXV0YXRlKGxvZ19sYWcgPSBsb2cobGFnKSkgJT4lIGdyb3VwX2J5KHNfbnVtLCB0cmlhbF9udW0sIHJvdW5kLCBwaGFzZSkgJT4lIHNsaWNlKC0xKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoc3ViaiA9IGFzLmZhY3RvcihzX251bSkpDQoNCmdncGxvdChsYWdfZGF0YSwgYWVzKHg9bGFnKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEwKSArIHhsaW0oNTAsMzAwKSArIGZhY2V0X3dyYXAoIH4gc19udW0pDQoNCiNnZ3Bsb3QobGFnX2RhdGEsIGFlcyh4PWxvZ19sYWcpKSAgKyBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IC4wMSkgKyBmYWNldF93cmFwKCB+IHNfbnVtKQ0KDQpmaWx0X2xhZyA8LSBsYWdfZGF0YSAlPiUgZ3JvdXBfYnkoc19udW0pICU+JSBmaWx0ZXIobG9nX2xhZyA8IChtZWFuKGxvZ19sYWcpICsgMypzZChsb2dfbGFnKSkgLCBsb2dfbGFnID4gKG1lYW4obG9nX2xhZykgLSAzKnNkKGxvZ19sYWcpKSkgJT4lIHVuZ3JvdXAoKQ0KDQpnZ3Bsb3QoZmlsdF9sYWcsIGFlcyh4PWxhZykpICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxMCkgICsgZmFjZXRfd3JhcCh+c19udW0pICsgeGxpbSg1MCwzNTApDQoNCmdncGxvdChmaWx0X2xhZywgYWVzKHg9bG9nX2xhZykpICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAuMDIpICsgZmFjZXRfd3JhcCh+c19udW0pDQoNCg0KDQpgYGANCmBgYHtyfQ0KIyMgd2l0aCBhIHJ1biwgcGxvdCB0aGUgbWVhbiBsYWcgDQpyb3VuZF9maWx0X2xhZyA8LSBmaWx0X2xhZyAlPiUgDQogIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kLCByb3VuZCwgcGhhc2UpICU+JQ0KICBzdW1tYXJpc2UodHJpYWxfbnVtID0gZmlyc3QodHJpYWxfbnVtKSwgbWVhbl9sYWcgPSBtZWFuKGxhZyksIG1lYW5fbG9nX2xhZyA9IG1lYW4obG9nX2xhZykpICU+JSBtdXRhdGUocm91bmRfbnVtID0gYXMuaW50ZWdlcihhcy5jaGFyYWN0ZXIocm91bmQpKSkNCg0KIyBwbG90IG1lYW4gbGFnIGFzIGEgZnVuY3Rpb24gb2Ygcm91bmQgbnVtYmVyDQpsYWdfYnlfcm91bmQgPC0gcm91bmRfZmlsdF9sYWcgJT4lIGdyb3VwX2J5KHNfbnVtLCByb3VuZF9udW0pICU+JSBzdW1tYXJpc2UobWVhbl9sYWcgPSBtZWFuKG1lYW5fbGFnKSkNCg0KZ2dwbG90KGxhZ19ieV9yb3VuZCwgYWVzKHg9IHJvdW5kX251bSwgeSA9IG1lYW5fbGFnKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArIGZhY2V0X3dyYXAofnNfbnVtKQ0KDQp0cmlhbF9maWx0X2xhZyA8LSByb3VuZF9maWx0X2xhZyAlPiUgDQogIGdyb3VwX2J5KHNfbnVtLCBuX3RyYXZlbF9zdGVwcywgdHJhdmVsX2tleV9jb25kLCBwaGFzZSkgJT4lDQogIHN1bW1hcmlzZSh0cmlhbF9udW0gPSBmaXJzdCh0cmlhbF9udW0pLCANCiAgICAgICAgICAgIG1lYW5fbGFnID0gbWVhbihtZWFuX2xhZyksIA0KICAgICAgICAgICAgbWVhbl9sb2dfbGFnID0gbWVhbihtZWFuX2xvZ19sYWcpKSAlPiUgdW5ncm91cCgpICU+JSBtdXRhdGUoc19udW0gPSBhcy5mYWN0b3Ioc19udW0pKQ0KDQpnZ3Bsb3QodHJpYWxfZmlsdF9sYWcsIA0KICAgICAgIGFlcyh4ID0gZmFjdG9yKG5fdHJhdmVsX3N0ZXBzKSwgeSA9IG1lYW5fbGFnLCBmaWxsID0gc19udW0pKSArIA0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IHNfbnVtKSwgc2l6ZSA9IDIpKyANCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHNfbnVtLCBjb2xvciA9IHNfbnVtKSwgc2l6ZSA9IDEuMikgKw0KICBmYWNldF9ncmlkKHBoYXNlIH4gdHJhdmVsX2tleV9jb25kKSArIHRoZW1lX21pbmltYWwoKQ0KDQpnZ3Bsb3QodHJpYWxfZmlsdF9sYWcsIA0KICAgICAgIGFlcyh4ID0gdHJhdmVsX2tleV9jb25kLCB5ID0gbWVhbl9sYWcsIGZpbGwgPSBzX251bSkpICsgDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gc19udW0pLCBzaXplID0gMikrIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gc19udW0sIGNvbG9yID0gc19udW0pLCBzaXplID0gMS4yKSArDQogIGZhY2V0X2dyaWQocGhhc2UgfiBuX3RyYXZlbF9zdGVwcykgKyB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQpgYGB7cn0NCg0KDQpncm91cF9sYWcgPC0gdHJpYWxfZmlsdF9sYWcgJT4lIGdyb3VwX2J5KG5fdHJhdmVsX3N0ZXBzLCB0cmF2ZWxfa2V5X2NvbmQsIHBoYXNlKSAlPiUgc3VtbWFyaXNlKGdtX2xhZyA9IG1lYW4obWVhbl9sYWcpLCBnbWxfbGFnID0gbWVhbihtZWFuX2xvZ19sYWcpKSAlPiUgdW5ncm91cCgpDQoNCmdncGxvdChncm91cF9sYWcsIGFlcyh4ID0gZmFjdG9yKG5fdHJhdmVsX3N0ZXBzKSwgeSA9IGdtX2xhZywgY29sb3IgPSB0cmF2ZWxfa2V5X2NvbmQpKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSB0cmF2ZWxfa2V5X2NvbmQpLCBzaXplID0gMikgKyBmYWNldF93cmFwKH5waGFzZSkgKyBnZW9tX3BvaW50KHNpemUgPSAyKQ0KICMgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGdtX3RocmVzaCAtIGdzZF90aHJlc2gsIHltYXggPSBnbV90aHJlc2grZ3NkX3RocmVzaCksIHdpZHRoID0gLjEsIHNpemUgPSAyKSArIA0KI2dlb21fcG9pbnQoc2l6ZSA9IDQpICsgeWxhYignZ3JvdXAgbWVhbiBleGl0IHRocmVzaG9sZCcpICsgeGxhYignIyB0cmF2ZWwgc3RlcHMnKSArIGxhYnMoY29sb3IgPSAndHJhdmVsIGVmZm9ydCcpICsgdGhlbWVfbWluaW1hbCgpDQoNCg0KDQpgYGANCmBgYHtyfQ0KaGFydmVzdF9sYWcgPC0gZmlsdF9sYWcgJT4lIHVuZ3JvdXAoKSAlPiUgZmlsdGVyKHBoYXNlID09ICJIQVJWRVNUIikNCmhsX21vZGVsIDwtIGxtZXIobG9nX2xhZyB+IHRyaWFsX251bSArIG5fdHJhdmVsX3N0ZXBzICsgdHJhdmVsX2tleV9jb25kICArICgxICsgdHJpYWxfbnVtICsgbl90cmF2ZWxfc3RlcHMgKyB0cmF2ZWxfa2V5X2NvbmQgfHN1YmopLCBkYXRhID0gaGFydmVzdF9sYWcsIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSJvcHRpbXgiLG9wdEN0cmw9bGlzdChtZXRob2Q9J25sbWluYicpKSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaGxfbW9kZWwpDQpgYGANCg0K
>>>>>>> origin/master